package com.yilin.platform.base_core.tools.cmbc.utils;


import com.google.gson.Gson;
import com.yilin.platform.base_core.commons.exception.BusinessException;
import com.yilin.platform.base_core.commons.utils.DateTimeUtil;
import com.yilin.platform.base_core.commons.utils.HttpService;
import com.yilin.platform.base_core.commons.utils.ParamUtil;
import com.yilin.platform.base_core.commons.utils.StringUtil;
import com.yilin.platform.base_core.interceptor.LoginInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Component
public class XmlBodyTools {
    private static Logger logger = LoggerFactory.getLogger(XmlBodyTools.class);
    private static String reqUrl = "http://127.0.0.1:9090/eweb/b2e/connect.do";//前置机请求地址
    @Value("${cmbc-bank-enterprise.req-url}")
    private String reqUrls;

    @PostConstruct
    public void setReqUrls() {
        reqUrl = this.reqUrls;
    }
    //TODO---------------------------------------------------------------------------------交易---------------------------------------------------------------------------------------------------------

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：单笔转账交易(Xfer)
     * 备注：公转公（本行，跨行），公转私-费用报销-代发工资（跨行） 支持操作子公司
     * 需要定义同步机制。 跨行公转私 交易 需输入常用用途代码|备注，备注可不输入
     *
     * @param tradeNo     客户端产生的交易唯一标志（支付单）
     * @param acntNo      付款账号
     * @param acntName    付款人名称
     * @param acntToNo    收款账号
     * @param acntToName  收款人名称
     * @param externBank  是否跨行（本行：0，跨行：1）
     * @param localFlag   汇路（本行转账：0，跨行转账- 小额支付系统：2，跨行转账-大额支付系统：3， 跨行转账-网银互联：5，跨行转账-自动计算汇路：9）
     * @param rcvCustType 收款人账户类型（1:对公；2:对私）
     * @param bankCode    收款人开户行行号（是否跨行标志<externBank>选择1时必填）
     * @param bankName    收款人开户行名称（大/小额、网银互联汇路此项必填）
     * @param bankAddr    收款人开户行地址（可选）
     * @param areaCode    收款行地区编号（可选）
     * @param amount      转账金额
     * @param explain     跨行公转私，需输入常用用途代码|备注（备注可不输入）
     * @param certNo      企业自制凭证号（8位以内的数字）
     *                    paramMap.put("tradeNo", null);
     *                    paramMap.put("acntNo", null);
     *                    paramMap.put("acntName", null);
     *                    paramMap.put("acntToNo", null);
     *                    paramMap.put("acntToName", null);
     *                    paramMap.put("externBank", null);
     *                    paramMap.put("localFlag", null);
     *                    paramMap.put("rcvCustType", null);
     *                    paramMap.put("bankCode", null);
     *                    paramMap.put("bankName", null);
     *                    paramMap.put("bankAddr", null);
     *                    paramMap.put("areaCode", null);
     *                    paramMap.put("amount", null);
     *                    paramMap.put("explain", null);
     *                    paramMap.put("certNo", null);
     */
    public static CmbcResData Xfer(String tradeNo, String acntNo, String acntName, String acntToNo, String acntToName, String externBank, String localFlag,
                                   String rcvCustType, String bankCode, String bankName, String bankAddr, String areaCode, String amount, String explain, String certNo) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("XR"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("cltcookie", "");//可选，客户端cookie，响应时原值返回
        dataBody.put("insId", objNullByObjNull(tradeNo));// （★） 指令ID，一条转账指令在客户端的唯一标识
        dataBody.put("acntNo", objNullByObjNull(acntNo));//（★） 付款账号
        dataBody.put("acntName", objNullByObjNull(acntName));//（★）付款人名
        dataBody.put("acntToNo", objNullByObjNull(acntToNo));//（★）收款账号
        dataBody.put("acntToName", objNullByObjNull(acntToName));//（★）收款人名称
        dataBody.put("externBank", objNullByObjNull(externBank));//（★）是否跨行 本行：0 跨行：1
        dataBody.put("localFlag", objNullByObjNull(localFlag));//（★）汇路 本行转账：0，<externBank>需输0| 跨行转账-小额支付系统：2，<externBank>需 输1 | 跨行转账-大额支付系统：3，<externBank>需 输1|跨行转账-网银互联：5，<externBank>需输1|  跨行转账-自动计算汇路：9，<externBank>需 输1
        dataBody.put("rcvCustType", objNullByObjNull(rcvCustType));//收款人账户类型：1:对公；2:对私；
        dataBody.put("bankCode", objNullByObjNull(bankCode));//收款人开户行行号（是否跨行标志<externBank>选择1时必填）
        dataBody.put("bankName", objNullByObjNull(bankName));//收款人开户行名称（★）(大/小额、网银互联汇 路此项必填)
        dataBody.put("bankAddr", objNullByObjNull(bankAddr));//收款人开户行地址(可选)
        dataBody.put("areaCode", objNullByObjNull(areaCode));//收款行地区编号(可选)
        dataBody.put("amount", objNullByObjNull(amount));//（★）转账金额
        dataBody.put("explain", objNullByObjNull(explain));//跨行公转私，需输入常用用途代码
        dataBody.put("certNo", objNullByObjNull(certNo));//企业自制凭证号(8位以内的数字)
        dataBody.put("actDate", "");//备用字段
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("Xfer");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：批量付款(batchXfer)
     * 备注：公转公（本行，跨行）支持 最大笔数：5000 借贷模式：一借一贷   公转私-费用报销（本行）不支持
     * 公转私-费用报销（跨行） 支持 最大笔数：5000 借贷模式：一借一贷 公转私-代发工资（本行） 不支持
     * 公转私-代发工资（跨行） 支持 最大笔数：5000 借贷模式：一借一贷
     *
     * @param batchNo   批次单号
     * @param payerAcct 付款账户
     * @param mapList   收款人信息 请按下面格式传值
     *                  map.put("tradeNo","");//   流水号
     *                  map.put("localFlag",""); //汇路 行内交易输入0跨行交易汇路为:6 小额实时支付7 大额实时支付 11 网银互联(暂不支持)
     *                  map.put("tradeCode","");// 企业自制凭证号 8位数字
     *                  map.put("accountType","");// 收款账户类型 必输 0.企业 1.个人卡 2.个人折 1
     *                  map.put("acntToNo",""); //收款账号
     *                  map.put("acntToName",""); //收款户名
     *                  map.put("bankCode",""); //收款行联行号行内转账不用输入大小额时填支付行号网银互联时填写网银互联支付行号
     *                  map.put("openBankName",""); // 收款行名 行内转账不输，跨行转账必须输入。大小额时填写支付行名 网银互联是填写网银互联支付行名
     *                  map.put("remark",""); //备注
     *                  map.put("useTo",""); //用用途代码 公转私时必输。 394 其他合法收入——运费 375 其他合法收入——资金退还 其他参考文档
     *                  map.put("amount",""); //转账金额
     */
    public static CmbcResData batchXfer(String batchNo, String payerAcct, List<Map<String, Object>> mapList) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("BX"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("insId", batchNo);//（★）  流水号
        dataBody.put("cltcookie", "");// 可选，客户端cookie，响应时原值返回
        dataBody.put("payerAcct", payerAcct);//（★） 付款账户
        dataBody.put("payType", 0);//（★）付款类型0:支付1:代发工资(预留、暂不支持)2:费用报销(预留、暂不支持)
        dataBody.put("totalRow", mapList.size());//（★）总记录数（★）
        StringBuilder fileContent = new StringBuilder();
        Double amt = 0d;
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> map = mapList.get(i);
            fileContent.append(String.format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s%s"
                    , map.get("tradeNo"), map.get("localFlag"), map.get("tradeCode"), "", "", map.get("accountType"),
                    map.get("acntToNo"), map.get("acntToName"), objNullByObjNull(map.get("bankCode")), objNullByObjNull(map.get("openBankName")),
                    objNullByObjNull(map.get("remark")), 0, "", "", objNullByObjNull(map.get("useTo")), map.get("amount"), (i == mapList.size() - 1 ? "" : "^")));
            amt += Double.parseDouble(map.get("amount").toString());
        }
        dataBody.put("totalAmt", amt);// （★）总金额数
        // （★）收款集合示例： 交易参考号|汇路|企业自制凭证号|支付业务种类|业务种类代码|收款账户类型|收款账号|收款户
        //名|收款行联行号|收款行名|备注|发送短信给收款方标识|收款方手机号|收款方email地址|常用用途
        //代码|金额^交易参考号|汇路|企业自制凭证号|支付业务种类|业务种类代码|收款账户类型|收款账号|
        //收款户名|收款行联行号|收款行名|备注|发送短信给收款方标识|收款方手机号|收款方email地址|常
        //用用途代码|金额
        dataBody.put("fileContent", fileContent);
        dataBody.put("certNo", "");//企业自制凭证号，非必输
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("batchXfer");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：批量转账制单(batchTransferXfer)
     * 备注：公转公（本行，跨行）支持 最大笔数：5000 借贷模式：一借一贷   公转私-费用报销（本行）不支持
     * 公转私-费用报销（跨行） 支持 最大笔数：5000 借贷模式：一借一贷 公转私-代发工资（本行） 不支持
     * 公转私-代发工资（跨行） 支持 最大笔数：5000 借贷模式：一借一贷
     *
     * @param batchNo   批次单号
     * @param payerAcct 付款账户
     * @param mapList   收款人信息 请按下面格式传值
     *                  map.put("tradeNo","");//   流水号
     *                  map.put("localFlag",""); //汇路 行内交易输入0跨行交易汇路为:6 小额实时支付7 大额实时支付 11 网银互联(暂不支持)
     *                  map.put("tradeCode","");// 企业自制凭证号 8位数字
     *                  map.put("accountType","");// 收款账户类型 必输 0.企业 1.个人卡 2.个人折 1
     *                  map.put("acntToNo",""); //收款账号
     *                  map.put("acntToName",""); //收款户名
     *                  map.put("bankCode",""); //收款行联行号行内转账不用输入大小额时填支付行号网银互联时填写网银互联支付行号
     *                  map.put("openBankName",""); // 收款行名 行内转账不输，跨行转账必须输入。大小额时填写支付行名 网银互联是填写网银互联支付行名
     *                  map.put("remark",""); //备注
     *                  map.put("useTo",""); //用用途代码 公转私时必输。 394 其他合法收入——运费 375 其他合法收入——资金退还 其他参考文档
     *                  map.put("amount",""); //转账金额
     */
    public static CmbcResData batchTransferXfer(String batchNo, String payerAcct, List<Map<String, Object>> mapList) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("BX"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("insId", batchNo);//（★）  流水号
        dataBody.put("cltcookie", "");// 可选，客户端cookie，响应时原值返回
        dataBody.put("payerAcct", payerAcct);//（★） 付款账户
        dataBody.put("payType", 0);//（★）付款类型0:支付1:代发工资(预留、暂不支持)2:费用报销(预留、暂不支持)
        dataBody.put("totalRow", mapList.size());//（★）总记录数（★）
        StringBuilder fileContent = new StringBuilder();
        Double amt = 0d;
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> map = mapList.get(i);
            fileContent.append(String.format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s%s"
                    , map.get("tradeNo"), map.get("localFlag"), map.get("tradeCode"), "", "", map.get("accountType"),
                    map.get("acntToNo"), map.get("acntToName"), objNullByObjNull(map.get("bankCode")), objNullByObjNull(map.get("openBankName")),
                    objNullByObjNull(map.get("remark")), 0, "", "", objNullByObjNull(map.get("useTo")), map.get("amount"), (i == mapList.size() - 1 ? "" : "^")));
            amt += Double.parseDouble(map.get("amount").toString());
        }
        dataBody.put("totalAmt", amt);// （★）总金额数
        // （★）收款集合示例： 交易参考号|汇路|企业自制凭证号|支付业务种类|业务种类代码|收款账户类型|收款账号|收款户
        //名|收款行联行号|收款行名|备注|发送短信给收款方标识|收款方手机号|收款方email地址|常用用途
        //代码|金额^交易参考号|汇路|企业自制凭证号|支付业务种类|业务种类代码|收款账户类型|收款账号|
        //收款户名|收款行联行号|收款行名|备注|发送短信给收款方标识|收款方手机号|收款方email地址|常
        //用用途代码|金额
        dataBody.put("fileContent", fileContent);
        dataBody.put("extendData", "");//扩展信息格式采用:key1=v1
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("batchTransfeXferr");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：批量费用报销、代发工资 (batchCostReimbNew)
     * 备注：
     * @param batchNo   批次单号
     * @param payType   付款类型（★）* 1:代发工资* 2:费用报销* 1
     * @param payerAcct 付款账户
     * @param mapList   收款人信息 请按下面格式传值
     *                  map.put("tradeNo","");//   流水号
     *                  map.put("acntToNo",""); //收款账号
     *                  map.put("acntToName","");//收款户名
     *                  map.put("useTo","");// 用途
     *                  map.put("remark",""); //备注
     *                  map.put("bankType",""); //0：同行，1：他行 必输 1
     *                  map.put("localFlag",""); //汇路 行内交易输入0跨行交易汇路为:6 小额实时支付7 大额实时支付 11 网银互联(暂不支持)
     *                  map.put("openBankName",""); // 收款行名 行内转账不输，跨行转账必须输入。大小额时填写支付行名 网银互联是填写网银互联支付行名
     *                  map.put("bankCode",""); //收款行行号
     *                  map.put("tradeCode",""); //企业自制凭证号 非必输 8
     *                  map.put("amount",""); //转账金额
     */
    public static CmbcResData batchCostReimbNew(String batchNo, String payerAcct,String payType,  List<Map<String, Object>> mapList) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("BXRN"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("insId", batchNo);//（★）  流水号
        dataBody.put("cltcookie", "");// 可选，客户端cookie，响应时原值返回
        dataBody.put("PayerAcNo", payerAcct);//（★） 付款账户
        dataBody.put("payType",payType);//（★）付款类型0:支付1:代发工资2:费用报销
        dataBody.put("totalRow", mapList.size());//（★）总记录数（★）
        dataBody.put("payModel","0");//转账模式 0：一借一贷，1：一借多贷（暂不支
        dataBody.put("fileContentType","1");//（★）总记录数（★）
        dataBody.put("secKeyEnc","");//（★）总记录数（★）
        dataBody.put("secKeyIndex","");//银行公钥的索引
        StringBuilder fileContent = new StringBuilder();
        Double amt = 0d;
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> map = mapList.get(i);
            fileContent.append(String.format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s%s"
                    , map.get("tradeNo"),  map.get("acntToNo"), map.get("acntToName"),  map.get("useTo"),objNullByObjNull(map.get("remark")),
                    map.get("bankType"),  map.get("localFlag"),objNullByObjNull(map.get("openBankName")), objNullByObjNull(map.get("bankCode")),
                  objNullByObjNull(map.get("tradeCode")), "","", "",map.get("amount"), (i == mapList.size() - 1 ? "" : "^")));
            amt += Double.parseDouble(map.get("amount").toString());
        }
        // （★）交易参考号|收款账号|收款账户名 |用途|备注|本他行标志|汇路|收款行行号|企业自制凭证号|备
        //用字段1|备用字段2|备用字段3|金额
        dataBody.put("fileContent", fileContent);
        dataBody.put("Usage","");//扩展信息格式采用:key1=v1
        dataBody.put("totalAmt",amt);//（★）总金额数
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("batchCostReimbNew");
        return postCmbcItemDataJ(returnMap);
    }
//TODO ---------------------------------------------------------------------查询-----------------------------------------------------------------------------------------

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：单笔转账交易结果查询(qryXfer)
     * 备注
     *
     * @param insId  支付单id
     * @param servid 服务器返回转账消息的标识
     */
    public static CmbcResData qryXfer(@Nullable String insId, @Nullable String servid) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QX"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("cltcookie", "");//可选，客户端cookie，响应时原值返回
        dataBody.put("insId", objNullByObjNull(insId));// （★） 指令ID，一条转账指令在客户端的唯一标识
        dataBody.put("svrId", objNullByObjNull(servid));//服务器返回转账消息的标识（非必输）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("qryXfer");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：批量付款对账(qryBatchXfer)
     * 备注
     *
     * @param batchTradeNo 批量付款单号
     */
    public static CmbcResData qryBatchXfer(String batchTradeNo) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QBX"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("insId", batchTradeNo);// （★） 指令ID，一条转账指令在客户端的唯一标识
        dataBody.put("payType", 0);//付款类型0:支付1:代发工资(预留、暂不支持)2:费用报销(预留、暂不支持)
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("qryBatchXfer");
        return postCmbcItemDataJ(returnMap);
    }
    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：批量费用报销、代发工资查询(qryBatchCostReimbNew)
     * 备注
     *
     * @param batchTradeNo 批量付款单号
     */
    public static CmbcResData qryBatchCostReimbNew(String batchTradeNo) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QBCR"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("insId", batchTradeNo);// （★） 指令ID，一条转账指令在客户端的唯一标识
        dataBody.put("payType", "2");//付款类型 传值不起作用，系统自动识别
        dataBody.put("fileContentType", "1");//1:明文  2:SM4加密
        dataBody.put("secKeyEnc", "");//如客户选择加密传输fileContent，则
        dataBody.put("secKeyIndex", "");//银行公钥的索引，
        dataBody.put("extent1", "");//扩展字段1
        dataBody.put("extent2", "");//扩展字段1
        dataBody.put("extent3", "");//扩展字段1
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("qryBatchCostReimbNew");
        return postCmbcItemDataJ(returnMap);
    }


    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：汇款交易结果明细查询(qryRemittDetail)
     * 备注
     *
     * @param acntNo     查询账号
     * @param qryFlag    批量付款单号
     * @param payChannel 汇路
     * @param dateFrom   开始日期
     * @param dateTo     截止日期
     * @param start      起始笔数
     * @param limit      查询笔数
     */
    public static CmbcResData qryRemittDetail(String acntNo, @Nullable String qryFlag, String payChannel, Date dateFrom, Date dateTo, Integer start, Integer limit) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QRD"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("cltcookie", "");//可选，客户端cookie，响应时原值返回
        dataBody.put("acntNo", acntNo);// （★） 查询账号
        dataBody.put("qryFlag", qryFlag == null ? 0 : qryFlag);//查询标志（★）0 - 成功，1 - 退款
        dataBody.put("payChannel", payChannel);//汇路（★） 2 - 小额，3-大额
        dataBody.put("dateFrom", DateTimeUtil.dateToString(dateFrom, "yyyy-MM-dd"));//开始日期（含）格式为YYYY-MM-DD（★）
        dataBody.put("dateTo", DateTimeUtil.dateToString(dateTo, "yyyy-MM-dd"));//截止日期（含）格式为YYYY-MM-DD（★）
        dataBody.put("startNo", start);//起始笔数，必须是有意义的数字（★）
        dataBody.put("queryRows", limit);//查询笔数(最大查询200笔)（★）
        dataBody.put("extendData", "");//
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("qryRemittDetail");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：定期账户明细查询交易(depositAccountDetail)
     * 备注
     *
     * @param acNo      待查明细的单位账号
     * @param beginDate 开始日期
     * @param endDate   截止日期
     */
    public static CmbcResData depositAccountDetail(String acNo, Date beginDate, Date endDate) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("DAD"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("AcNo", acNo);// （★） 待查明细的单位账号
        dataBody.put("BeginDate", DateTimeUtil.dateToString(beginDate, "yyyy-MM-dd"));//开始日期（含）格式为YYYY-MM-DD（★）
        dataBody.put("EndDate", DateTimeUtil.dateToString(endDate, "yyyy-MM-dd"));//截止日期（含）格式为YYYY-MM-DD（★）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("depositAccountDetail");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：银企直联明细下载(新)(trsDtlDownLoad)
     * 备注
     *
     * @param acntNo   查询账号
     * @param dateFrom 开始日期
     * @param dateTo   截止日期
     * @param start    起始笔数
     * @param limit    查询笔数
     */
    public static CmbcResData trsDtlDownLoad(String acntNo, Date dateFrom, Date dateTo, Integer start, Integer limit) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("TDD"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("acntNo", acntNo);// 查询账号（★）
        dataBody.put("dateFrom", DateTimeUtil.dateToString(dateFrom, "yyyy-MM-dd"));//开始日期（含）格式为YYYY-MM-DD（★）
        dataBody.put("dateTo", DateTimeUtil.dateToString(dateTo, "yyyy-MM-dd"));//截止日期（含）格式为YYYY-MM-DD（★）
        dataBody.put("startNo", start);// 起始笔数（★）
        dataBody.put("queryRows", limit);// 查询笔数（★）
        dataBody.put("typeCode", "");//借贷标记(暂不支持)
        dataBody.put("extent1", "");//扩展字段1（暂未启用）
        dataBody.put("extent2", "");//扩展字段2（暂未启用）
        dataBody.put("extent3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("trsDtlDownLoad");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能： 余额查询交易（新）(qryBalNew)
     * 备注
     *
     * @param acntNos 查询账号集合
     */
    public static CmbcResData qryBalNew(String[] acntNos) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QBN"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("cltcookie", "");//可选，客户端cookie，响应时原值返回
        String acntList = "";
        for (String str : acntNos) {
            acntList += "<acntNo>" + str + "</acntNo>";
        }
        dataBody.put("acntList", acntList);// 查询账号（★）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("qryBalNew");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能： 历史余额查询(qryHistoryBal)
     * 备注
     *
     * @param acntNo  查询账号（★）
     * @param qryDate 查询时间（★）
     */
    public static CmbcResData qryHistoryBal(String acntNo, @Nullable Date qryDate) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QHB"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("cltcookie", "");//可选，客户端cookie，响应时原值返回
        dataBody.put("acntNo", acntNo);// 查询账号（★）
        dataBody.put("qryDate", qryDate == null ? "" : DateTimeUtil.dateToString(qryDate, "yyyy-MM-dd"));//查询时间(若不输入，则默认查询当日余额)(格  式：yyyy-MM-dd)
        dataBody.put("extendData", "");// 备用字段(暂不支持)
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("qryHistoryBal");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：  交易明细查询(qryTrsDtl)
     * 备注
     *
     * @param acntNo   查询账号（★）
     * @param dateFrom 开始日期（★）
     * @param dateTo   截止日期（★）
     * @param startNo  开始条数（★）
     * @param endNo    结束条数（★）
     */
    public static CmbcResData qryTrsDtl(String acntNo, Date dateFrom, Date dateTo, Integer startNo, Integer endNo) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QTD"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("cltcookie", "");//可选，客户端cookie，响应时原值返回
        dataBody.put("acntNo", acntNo);// 查询账号（★）
        dataBody.put("dateFrom", DateTimeUtil.dateToString(dateFrom, "yyyy-MM-dd"));//开始日期（含）格式为YYYY-MM-DD（★）
        dataBody.put("dateTo", DateTimeUtil.dateToString(dateTo, "yyyy-MM-dd"));//截止日期（含）格式为YYYY-MM-DD（★）
        dataBody.put("startNo", startNo);// 开始条数，必须是有意义的数字
        dataBody.put("endNo", endNo);// 结束条数，必须是有意义的数字
        dataBody.put("typeCode", "");// 借贷标记(暂不支持)
        dataBody.put("extent1", "");//扩展字段1（暂未启用）
        dataBody.put("extent2", "");//扩展字段2（暂未启用）
        dataBody.put("extent3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("qryTrsDtl");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能： 明细对账单查询(QryDebtDetialList)
     * 备注
     *
     * @param acNo         银行账号
     * @param qryStartDate 开始日期（★）
     * @param qryEndDate   截止日期（★）
     * @param currentIndex 起始笔数（★）
     * @param pageSize     查询笔数（★）
     * @param customNo     成员客户号（★）
     */
    public static CmbcResData qryDebtDetialList(String acNo, Date qryStartDate, Date qryEndDate, Integer currentIndex, Integer pageSize, String customNo) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QDDL"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("acNo", acNo);//银行账号（★）
        dataBody.put("qryStartDate", DateTimeUtil.dateToString(qryStartDate, "yyyy-MM-dd"));//开始日期 （含） （★） yyyy-MM-dd
        dataBody.put("qryEndDate", DateTimeUtil.dateToString(qryEndDate, "yyyy-MM-dd"));//截止日期 （含） （★） yyyy-MM-dd
        dataBody.put("currentIndex", currentIndex);//起始笔数（★）
        dataBody.put("pageSize", pageSize);//查询笔数（★）
        dataBody.put("customNo", customNo);//成员客户号 此字段为空查询本公司明细对账信息;如果不为空,则查询所填写的成员公司明细对账信息;(成员公司与本公司必须有签约关系)
        dataBody.put("extFields1", "");//扩展字段1（暂未启用）
        dataBody.put("extFields2", "");//扩展字段2（暂未启用）
        dataBody.put("extFields3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("QryDebtDetialList");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：  已填写调节表查询(QryDebtReChkDetail)
     * 备注
     *
     * @param acNo      银行账号
     * @param customNo  成员客户号（★）
     * @param checkDate 对账日期（★）
     */
    public static CmbcResData qryDebtReChkDetail(String acNo, String customNo, Date checkDate) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("DRCD"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("customNo", customNo);//成员客户号 此字段为空查询本公司明细对账信息;如果不为空,则查询所填写的成员公司明细对账信息;(成员公司与本公司必须有签约关系)
        dataBody.put("acNo", acNo);//银行账号（★）
        dataBody.put("checkDate", DateTimeUtil.dateToString(checkDate, "yyyyMM"));//对账日期 （含） （★）yyyyMM
        dataBody.put("extFields1", "");//扩展字段1（暂未启用）
        dataBody.put("extFields2", "");//扩展字段2（暂未启用）
        dataBody.put("extFields3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("QryDebtReChkDetail");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：  对账结果查询(QryDebtResultList)
     * 备注
     *
     * @param acNo         银行账号
     * @param customNo     成员客户号（★）
     * @param qryType      查询类型 (
     * @param qryStartDate 开始日期（★）
     * @param qryEndDate   截止日期（★）
     * @param currentIndex 起始笔数（★）
     * @param pageSize     查询笔数（★）
     */
    public static CmbcResData qryDebtResultList(String acNo, @Nullable String customNo, Integer qryType, Date qryStartDate, Date qryEndDate, Integer currentIndex, Integer pageSize) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QDRL"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("customNo", objNullByObjNull(customNo));//成员客户号 此字段为空查询本公司明细对账信息;如果不为空,则查询所填写的成员公司明细对账信息;(成员公司与本公司必须有签约关系)
        dataBody.put("qryType", qryType);//查询类型 (★)
        dataBody.put("acNo", acNo);//银行账号（★）
        dataBody.put("qryStartDate", DateTimeUtil.dateToString(qryStartDate, "yyyyMM"));//开始日期( （含） （★）yyyyMM
        dataBody.put("qryEndDate", DateTimeUtil.dateToString(qryEndDate, "yyyyMM"));//截止日期（含） （★）yyyyMM
        dataBody.put("currentIndex", currentIndex);//起始笔数（★）
        dataBody.put("pageSize", pageSize);//查询笔数（★）
        dataBody.put("extFields1", "");//扩展字段1（暂未启用）
        dataBody.put("extFields2", "");//扩展字段2（暂未启用）
        dataBody.put("extFields3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("QryDebtResultList");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：  可填写对账单回执列表(QryVerifyAccRecList)
     * 备注
     *
     * @param startNo   起始笔数（★）
     * @param queryRows 查询笔数（★）
     * @param customNo  成员客户号（★）
     * @param qryDate   查询时间（★）
     */
    public static CmbcResData qryVerifyAccRecList(Integer startNo, Integer queryRows, String customNo, Date qryDate) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QVAR"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("qryYear", DateTimeUtil.dateToString(qryDate, "yyyyMM"));//查询年份（★）
        dataBody.put("qryMonth", DateTimeUtil.dateToString(qryDate, "yyyyMM"));//查询月份（★） MM
        dataBody.put("startNo", startNo);//起始笔数 （★）
        dataBody.put("queryRows", queryRows);//查询笔数 （★）
        dataBody.put("customNo", customNo);//成员客户号 此字段为空查询本公司明细对账信息;如果不为空,则查询所填写的成员公司明细对账信息;(成员公司与本公司必须有签约关系)
        dataBody.put("extendReq1", "");//扩展字段1（暂未启用）
        dataBody.put("extendReq2", "");//扩展字段2（暂未启用）
        dataBody.put("extendReq3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("QryVerifyAccRecList");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：  对账日期查询(QryVerifyAccRecordDate)
     * 备注
     *
     * @param customNo 成员客户号（★）
     * @param qryDate  查询时间（★）
     */
    public static CmbcResData qryVerifyAccRecordDate(String customNo, Date qryDate) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("QARD"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("qryYear", DateTimeUtil.dateToString(qryDate, "yyyyMM"));//查询年份（★）
        dataBody.put("customNo", customNo);//成员客户号 此字段为空查询本公司明细对账信息;如果不为空,则查询所填写的成员公司明细对账信息;(成员公司与本公司必须有签约关系)
        dataBody.put("extendReq1", "");//扩展字段1（暂未启用）
        dataBody.put("extendReq2", "");//扩展字段2（暂未启用）
        dataBody.put("extendReq3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("QryVerifyAccRecordDate");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：  对账单回执确认(VerifyAccRecConf)
     * 备注
     *
     * @param insId    一条转账指令在客户端的唯一标识（★）
     * @param confDate 查询年份（★）
     * @param customNo 成员客户号（★）
     * @param confMap  审核数据  key有两个 分别为startNo 对账单顺序号和 actNo 账号
     */
    public static CmbcResData verifyAccRecConf(String insId, Date confDate, String customNo, List<Map<String, Object>> confMap) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("VARC"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("insId", insId);//指令ID，一条转账指令在客户端的唯一标识
        dataBody.put("confDate", DateTimeUtil.dateToString(confDate, "yyyyMM"));//查询年份（★）yyyyMM格式
        dataBody.put("customNo", customNo);//成员客户号 此字段为空查询本公司明细对账信息;如果不为空,则查询所填写的成员公司明细对账信息;(成员公司与本公司必须有签约关系)
        StringBuilder fileContent = new StringBuilder();
        for (int i = 0; i < confMap.size(); i++) {
            fileContent.append(String.format("0|%s|%s%s", confMap.get(i).get("startNo"), confMap.get(i).get("actNo"), (i == confMap.size() - 1 ? "" : "^")));
        }
        dataBody.put("confContent", fileContent);//审核数据 竖线“|”分割数据元素，以尖号“^”为数据行分割符（★）
        dataBody.put("extendReq1", "");//扩展字段1（暂未启用）
        dataBody.put("extendReq2", "");//扩展字段2（暂未启用）
        dataBody.put("extendReq3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("VerifyAccRecConf");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能： 活期存款列表查询交易(qryAcctList)
     * 备注 已写完，返回空完全正确
     */
    public static CmbcResData qryAcctList() {
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(null);
        returnMap.setTrnCode("qryAcctList");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：   利率查询(InterestSettlementQryB2e)
     * 备注
     *
     * @param insId     交易流水号（★）
     * @param acNo      银行账号（★）
     * @param checkDate 查询日期（★）
     */
    public static CmbcResData interestSettlementQryB2e(String insId, String acNo, Date checkDate) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("insId", insId);// （★） 交易流水号
        dataBody.put("acNo", acNo);//银行账号（★）
        dataBody.put("qryDate", DateTimeUtil.dateToString(checkDate, "yyyy-MM-dd"));//查询日期（形如：yyyy-MM-dd）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("InterestSettlementQryB2e");
        return postCmbcItemDataJ(returnMap);
    }


    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：通过行名查询行号(批量)(B2eBatchBankNo)
     * 备注
     *
     * @param bankNames 银行，名称（★）
     */

    public static CmbcResData b2eBatchBankNo(List<String> bankNames) {
        Map<String, Object> dataBody = new HashMap<>();
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (String bankName : bankNames) {
            Map<String, Object> objectMap = new HashMap<>();
            objectMap.put("bankName", bankName);
            mapList.add((objectMap));
        }
        dataBody.put("trnId", DateTimeUtil.dateNo("BN"));// （★） 交易流水号
        dataBody.put("list", new Gson().toJson(mapList));// （★） 交易流水号
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("B2eBatchBankNo");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：获取行名查询行号结果（批量）(B2eQryBatchBankNo)
     * 备注
     *
     * @param origSvrIds 调用B2eBatchBankNo接口返回的服务流水号
     */
    public static CmbcResData b2eQryBatchBankNo(String origSvrIds) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("BQBB"));// （★） 交易流水号
        dataBody.put("origSvrId", origSvrIds);// （★） 交易流水号
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("B2eQryBatchBankNo");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：公告查询(EntNoticeQryB2e)
     * 备注
     */
    public static CmbcResData entNoticeQryB2e() {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("ENQB"));// （★） 交易流水号
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("EntNoticeQryB2e");
        return postCmbcItemDataJ(returnMap);
    }

    //TODO-------------------------------------------------------------------操作---------------------------------------------------------------------------------------------

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能： 网上对账开通信息维护(DebtMaintainB2e)
     * 备注
     *
     * @param insId       一条转账指令在客户端的唯一标识
     * @param contactName 联系人名称（★）
     * @param companyTel  公司电话（★）
     * @param phone       联系人手机
     * @param type        操作类型（★）
     */
    public static CmbcResData debtMaintainB2e(String insId, String contactName, String companyTel, String phone, Integer type) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("DMB"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("insId", insId);//一条转账指令在客户端的唯一标识
        dataBody.put("contactName", contactName);//联系人名称（★）
        dataBody.put("companyTel", companyTel);//公司电话（★）
        dataBody.put("phone", phone);//联系人手机
        dataBody.put("operateType", type);//操作类型（★） 0：开通，1：修改，2：关闭
        dataBody.put("extent1", "");//扩展字段1（暂未启用）
        dataBody.put("extent2", "");//扩展字段2（暂未启用）
        dataBody.put("extent3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("DebtMaintainB2e");
        return postCmbcItemDataJ(returnMap);
    }


    // TODO------------------------------------------------------------------下载----------------------------------------------------------------------------------------------

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能： 交易明细对账单PDF下载(ElectNotePrint)
     * 备注
     *
     * @param acntNo    查询账号（★）
     * @param startDate 开始日期（★）
     * @param endDate   截止日期（★）
     */
    public static CmbcResData electNotePrint(String acntNo, Date startDate, Date endDate) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("trnId", DateTimeUtil.dateNo("ENP"));// （★） 客户端产生的交易唯一标志（必输，但无作 用）
        dataBody.put("acctNo", acntNo);//待查明细的单位账号（★）
        dataBody.put("startDate", DateTimeUtil.dateToString(startDate, "yyyy-MM-dd"));//开始日期（含）格式为YYYY-MM-DD（★）
        dataBody.put("endDate", DateTimeUtil.dateToString(endDate, "yyyy-MM-dd"));//截止日期（含）格式为YYYY-MM-DD（★）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("ElectNotePrint");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：客户账单回单下载（支持最多3个同时下载）(b2eElectNoteDownLoadNew)
     * 备注
     *
     * @param insId     一条转账指令在客户端的唯一标识（★）
     * @param acNo      账号（★）
     * @param innerNos  回单编号（★）
     * @param fileNames 文件名称（★）
     * @param operFlag  操作标识下载（★）
     */
    public static CmbcResData b2eElectNoteDownLoadNew(String acNo, String[] innerNos, String[] fileNames, Integer operFlag, @Nullable Integer needSign) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("insId",  DateTimeUtil.dateNo("BEND"));// 一条转账指令在客户端的唯一标识（★）
        dataBody.put("AcNo", acNo);//账号（★）
        dataBody.put("innerNo", String.join("|", innerNos));//回单编号（★）回单查询返回回单编号（base64），多个回单编号以“|”隔开
        dataBody.put("FileName", String.join("|", fileNames));//文件名称（★）回单查询返回文件名称，多个回单的文件名称以“|”隔开
        dataBody.put("OperFlag", operFlag);//操作标识下载 0：T日回单，1：T-n日回单
        dataBody.put("NeedSign", needSign == null ? 0 : needSign);//是否添加可信签章0-不添加。 1-添加。默认为0
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("b2eElectNoteDownLoadNew");
        return postCmbcItemDataJ(returnMap);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：客户回单查询(ElectnoteListQry) (支持T0，T-n日回单)
     * 备注
     *
     * @param saAcctNo     账号（★）
     * @param qryStartDate 查询起始日期（★）
     * @param qryEndDate   查询截止日期（★）
     * @param printState   打印状态0
     * @param minMoney     发生额范围小
     * @param maxMoney     发生额范围大
     * @param loanFlag     借贷标识
     * @param pageNo       当前页码
     * @param pageSize     查询笔数
     */
    public static CmbcResData electnoteListQry(String saAcctNo, Date qryStartDate, Date qryEndDate
            , @Nullable Integer printState, @Nullable Double minMoney, @Nullable Double maxMoney,
                                               @Nullable Integer loanFlag, @Nullable Integer pageNo, @Nullable Integer pageSize) {
        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("insId", DateTimeUtil.dateNo("ELQ"));// 一条转账指令在客户端的唯一标识（★）
        dataBody.put("saAcctNo", saAcctNo);//账号（★）
        dataBody.put("qryStartDate", DateTimeUtil.dateToString(qryStartDate, "yyyy-MM-dd"));//查询起始日期（形如：yyyy-MM-dd）（★）
        dataBody.put("qryEndDate", DateTimeUtil.dateToString(qryEndDate, "yyyy-MM-dd"));//查询截止日期（形如：yyyy-MM-dd）（★）
        dataBody.put("printState", printState == null ? 2 : printState);//打印状态0—全部，1—已打印，2未打印，不输默认为2
        dataBody.put("minMoney", objNullByObjNull(minMoney));//发生额范围小(15,2)
        dataBody.put("maxMoney", objNullByObjNull(maxMoney));//发生额范围大(15,2)
        dataBody.put("loanFlag", objNullByObjNull(loanFlag));//借贷标识(0-借 1-贷)非必输，不输入默认全部
        dataBody.put("pageNo", objNullByObjNull(pageNo));//当前页码
        dataBody.put("pageSize", objNullByObjNull(pageSize));//查询笔数
        dataBody.put("extendReq1", "");//扩展字段1（暂未启用）
        dataBody.put("extendReq2", "");//扩展字段2（暂未启用）
        dataBody.put("extendReq3", "");//扩展字段3（暂未启用）
        XmlReturnMap returnMap = new XmlReturnMap();
        returnMap.setBodyMap(dataBody);
        returnMap.setTrnCode("ElectnoteListQry");
        return postCmbcItemDataJ(returnMap);
    }

    private static Object objNullByObjNull(Object str) {
        return str == null ? "" : str;
    }

    // 公共请求
    public static CmbcResData postCmbcItemDataJ(XmlReturnMap returnMap) {
        String xmlReq = XmlBuilder.convertToReqXml(returnMap);
        logger.info("民生银行请求数据，请求接口:["+returnMap.getTrnCode()+"],请求xml:["+xmlReq+"]");
        try {
            URL urlObject = new URL(reqUrl);
            HttpURLConnection connection = (HttpURLConnection) urlObject.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/xml; charset=GB2312");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
            outputStream.write(xmlReq.getBytes(StandardCharsets.UTF_8));
            outputStream.flush();
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "GB2312"));
                String line;
                StringBuilder response = new StringBuilder();
                while ((line = reader.readLine()) != null) response.append(line);
                CmbcResData cmbcResData = null;
                logger.info("民生银行返回数据，返回接口:["+returnMap.getTrnCode()+"],返回xml:["+response.toString()+"]");
                if (StringUtil.isNotEmpty(response.toString()))
                    cmbcResData = XmlBuilder.parseXmlDataResponse(response.toString(), returnMap.getTrnCode());//xml
                if (cmbcResData != null && !cmbcResData.getCode().equals("0")){
                    logger.info("民生银行返回数据，错误代码:["+cmbcResData.getTrnCode()+"],返回xml:["+cmbcResData.getMessage()+"]");
                    throw new BusinessException("错误代码：" + cmbcResData.getCode() + "错误信息：" + cmbcResData.getMessage());
                }
                return cmbcResData;
            } else {
                BufferedReader errorReader = new BufferedReader(new InputStreamReader(connection.getErrorStream(), "GB2312"));
                String line;
                StringBuilder errorResponse = new StringBuilder();
                while ((line = errorReader.readLine()) != null) errorResponse.append(line);
                throw new BusinessException("民生银行请求失败，失败信息: " + responseCode + ", " + errorResponse.toString());
            }
        } catch (IOException e) {
            throw new BusinessException("民生银行请求错误信息" + e.getMessage());
        }
    }


}
